package libra.startup;

import java.io.IOException;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import javax.servlet.ServletContext;
import javax.sql.DataSource;

import org.apache.dubbo.config.spring.context.annotation.EnableDubbo;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.ImportResource;
import org.springframework.context.annotation.PropertySource;
import org.springframework.format.FormatterRegistry;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.jdbc.datasource.DataSourceTransactionManager;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.annotation.EnableTransactionManagement;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ViewResolverRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import com.alibaba.druid.pool.DruidDataSource;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser.Feature;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;

import libra.constans.PropConstants;


//标注配置类
@Configuration
//开启web配置
@EnableWebMvc 
//开启定时器配置
@EnableScheduling 
//开启事务配置
@EnableTransactionManagement 
//指定包扫描
@ComponentScan(value="libra")
//读取properties文件
@PropertySource(value={"classpath:config.properties"},encoding="UTF-8")

//@EnableDubbo
// 导入外部的Dubbo.xml文件配置进IOC容器，不需要@EnableDubbo注解
@ImportResource(value = {"classpath:mvc_provider.xml"})
public class WebConfig extends WebMvcConfigurerAdapter implements InitializingBean {

	@Autowired
	private PropConstants prop;

	/**
	 * 配置自定义转换器
	 */
//	@Override
//	public void addFormatters(FormatterRegistry registry) {
//		// TODO Auto-generated method stub
//		registry.addConverter(new DateConverter());
//		super.addFormatters(registry);
//	}

	//视图解析器
	@Override
	public void configureViewResolvers(ViewResolverRegistry registry) {
		registry.jsp("/WEB-INF/pages/", ".jsp");
	}

	//静态资源访问·
	@Override
	public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) {
		configurer.enable();
	}
	
	//拦截器,按照添加顺序执行
	@Override
	public void addInterceptors(InterceptorRegistry registry) {
//		registry.addInterceptor( sysInfoInterceptor ).addPathPatterns("/sys/**").excludePathPatterns("/sys/auth/**");
	}
	
	
	//配置RestTemplate,便于发送请求
	@Bean
	public RestTemplate restTemplate() {
		RestTemplate restTemplate = new RestTemplate(  );
		List<HttpMessageConverter<?>> list = new ArrayList<HttpMessageConverter<?>>();
		list.add(new StringHttpMessageConverter(Charset.forName("UTF-8")));
		list.add(new ByteArrayHttpMessageConverter());
		list.add(new AllEncompassingFormHttpMessageConverter());
		list.add(new MappingJackson2HttpMessageConverter());
		restTemplate.setMessageConverters(list);
		return restTemplate;
	}
	
	//配置ObjectMapper,便于json转换
	@Bean
	public ObjectMapper mapper() {
		ObjectMapper mapper =  new ObjectMapper();
		mapper.configure(Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);//忽略换行符
		mapper.configure(Feature.ALLOW_SINGLE_QUOTES, true);//含有单引号，为true时，则：'\''保存为'''
		mapper.configure(Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true);//含有反斜杠的转义字符，为true时，则：\'保存为’
		mapper.configure(Feature.STRICT_DUPLICATE_DETECTION, true);//不检查重复的key值，true时，检查是否有重复的key值，若有则报错
		return mapper;
	}
	
	//配置DataSource
	@Bean
	public DataSource dataSource() throws Exception {
		DruidDataSource dataSource = new DruidDataSource();
		dataSource.setUrl(prop.jdbcUrl);
		dataSource.setDriverClassName(prop.jdbcDriverClassName);
		dataSource.setUsername(prop.jdbcUsername);
		dataSource.setPassword(prop.jdbcPassword);
		return dataSource;
	}
	
	//配置JdbcTemplate
	@Bean
	public JdbcTemplate jt() throws Exception {
//		Spring对@Configuration的配置类会特殊处理：给容器中加组件的方法,在配置类中多次调用,只会在容器中创建一次,其余被调用的地方直接从容器中查找组件
		return new JdbcTemplate( dataSource() ); 
//		return new JdbcTemplate(dataSource);
	}
	
	//配置事务管理器,配合@EnableTransactionManagement注解使用
	@Bean
	public PlatformTransactionManager manager( @Autowired DataSource dataSource ) throws Exception {
		return new DataSourceTransactionManager( dataSource );
	}
	
	@Bean
	public SimpleDateFormat sdf() {
		return new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
	}
	
	@Autowired
	private ServletContext sc;
	
	@Autowired
	private ApplicationContext applicationContext;
	@Override
	public void afterPropertiesSet() throws Exception {
		
		RequestMappingHandlerMapping mapping = applicationContext.getBean(RequestMappingHandlerMapping.class);
		// 获取url与类和方法的对应信息
//		Map<RequestMappingInfo, HandlerMethod> map = mapping.getHandlerMethods();
//		for( Entry<RequestMappingInfo, HandlerMethod> entry : map.entrySet() ) {
//			RequestMappingInfo info = entry.getKey();
//			HandlerMethod method = entry.getValue();
//			Class<?> controllerClass =  method.getMethod().getDeclaringClass();
//				PatternsRequestCondition p = info.getPatternsCondition();
//				for (String url : p.getPatterns()) { 
//					System.out.println( url );
//	            }
//		}
	}
}
